package com.baidu.dtx.inventory.service.impl;

import com.baidu.dtx.common.enums.TccEnum;
import com.baidu.dtx.inventory.dto.InventoryDTO;
import com.baidu.dtx.inventory.entities.Inventory;
import com.baidu.dtx.inventory.entities.InventoryDetail;
import com.baidu.dtx.inventory.mapper.InventoryDetailMapper;
import com.baidu.dtx.inventory.mapper.InventoryMapper;
import com.baidu.dtx.inventory.service.InventoryService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @author shilei
 * @create 2021-05-13 22:34
 */
@Service
@Slf4j
public class InventoryServiceImpl implements InventoryService {

    @Resource
    private InventoryDetailMapper inventoryDetailMapper;
    @Resource
    private InventoryMapper inventoryMapper;

    @Hmily(confirmMethod = "confirmMethod",cancelMethod = "cancelMethod")
    @Transactional
    @Override
    public String decrease(InventoryDTO inventoryDTO) {
        log.info("-------进入库存的try-------");

        //1库存数判断 库存不够或者顾客下单数高于实际库存
        Inventory inventory=new Inventory();
        inventory.setProductId(inventoryDTO.getProductId());
        inventory=this.inventoryMapper.selectOne(inventory);
        if(inventory.getTotalInventory()<=0 || inventory.getTotalInventory()<inventoryDTO.getCount()){
            throw new RuntimeException("-----库存不够或者下单数高于实际库存");
        }

        //2.幂等性判断 订单号只能有一笔订单 订单号为null说明还未插入过，否则就是重复订单
        InventoryDetail detail = new InventoryDetail();
        detail.setOrderNo(inventoryDTO.getOrderNo());
        if (this.inventoryDetailMapper.selectOne(detail) != null) {
            throw new RuntimeException("存在订单号！");
        }

        //3 插入库存明细
        BeanUtils.copyProperties(inventoryDTO,detail);
        detail.setTxStatus(TccEnum.TRY.getCode());
        this.inventoryDetailMapper.insertSelective(detail);

        //4 减库存
        Inventory updateInventory=new Inventory();
        updateInventory.setProductId(inventoryDTO.getProductId());
        //总库存-1
        updateInventory.setTotalInventory(-inventoryDTO.getCount());
        //冻结库存+1 //这里底层使用了一条SQL来进行三条SQL的通用,使用正负数传参来限制库存参数
        updateInventory.setLockInventory(+inventoryDTO.getCount());
        // 库存业务逻辑处理
        this.inventoryMapper.decrease(updateInventory);

        return "decrease ok";
    }

    @Transactional
    public String confirmMethod(InventoryDTO inventoryDTO){
        log.info("-------进入库存的confirm-------");
        //1 幂等性判断
        InventoryDetail inventoryDetail=new InventoryDetail();
        inventoryDetail.setOrderNo(inventoryDTO.getOrderNo());
        inventoryDetail=this.inventoryDetailMapper.selectOne(inventoryDetail);
        if(inventoryDetail.getTxStatus()==TccEnum.CONFIRM.getCode()){
            throw new RuntimeException("该订单号，已经confirm!");
        }

        //2 修改订单状态，从try→confirm
        InventoryDetail updateInventoryDetail=new InventoryDetail();
        updateInventoryDetail.setId(inventoryDetail.getId());
        updateInventoryDetail.setTxStatus(TccEnum.CONFIRM.getCode());
        this.inventoryDetailMapper.updateByPrimaryKeySelective(updateInventoryDetail);

        //3 库存confirm阶段处理
        Inventory inventory=new Inventory();
        inventory.setProductId(inventoryDTO.getProductId());
        //实际库存不动，设置为零
        inventory.setTotalInventory(0);
        //冻结库存 - 1
        inventory.setLockInventory(-inventoryDTO.getCount());
        // 库存业务逻辑处理
        this.inventoryMapper.decrease(inventory);

        return "confirmMethod OK";
    }

    @Transactional
    public String cancelMethod(InventoryDTO inventoryDTO){
        log.info("-------进入库存的cancel-------");
        //1 幂等性判断
        InventoryDetail inventoryDetail=new InventoryDetail();
        inventoryDetail.setOrderNo(inventoryDTO.getOrderNo());
        inventoryDetail=this.inventoryDetailMapper.selectOne(inventoryDetail);
        if(inventoryDetail.getTxStatus()==TccEnum.CANCEL.getCode()){
            throw new RuntimeException("该订单号，已经cancel!");
        }

        //2 修改订单状态，从try→CANCEL
        InventoryDetail updateInventoryDetail=new InventoryDetail();
        updateInventoryDetail.setId(inventoryDetail.getId());
        updateInventoryDetail.setTxStatus(TccEnum.CANCEL.getCode());
        this.inventoryDetailMapper.updateByPrimaryKeySelective(updateInventoryDetail);

        //3 库存CANCEL阶段处理,实际库存和冻结库存反向回退 逆向操作
        Inventory inventory=new Inventory();
        inventory.setProductId(inventoryDTO.getProductId());
        //实际库存 + 1
        inventory.setTotalInventory(+inventoryDTO.getCount());
        //冻结库存 - 1
        inventory.setLockInventory(-inventoryDTO.getCount());
        // 库存业务逻辑处理
        this.inventoryMapper.decrease(inventory);

        return "cancelMethod OK";
    }


}
